PHLEGM v6 NES vblank completed-frame latch fix
Date: 2026-10-02
Checkpoint timestamp lineage: 2026-0929-2056-1024

Symptom
- Donkey Kong (NROM-128, mapper 0) could present a uniform gray NES display after the prior device-clocked frame-latch change.

Diagnosis
- The prior NES latch sampled the emulated PPU at the pre-render clear event.
- A completed NES visible frame is available at vblank entry, before the CPU services the NMI edge.
- Sampling after the vblank handler has run can observe temporary PPUMASK/VRAM/OAM state instead of the just-completed visible frame.
- The supplied Donkey Kong cartridge confirmed the reset vector ($C79E), mapper 0/NROM layout, and PPU-status startup path. Its saved powered session was captured during normal startup RAM clearing and was not itself evidence of an opcode hang.

Fix
- Move the NES device-produced framebuffer latch from pre-render clear to vblank entry.
- Latch before setting the CPU-visible vblank flag / pending NMI.
- Keep host refresh presentation-only for NES device-latched frames.
- Keep pre-render responsible for clearing PPU status bits only.
- Preserve the generic native-raster rendering path for non-NES devices.

Validation
- tools/validate_nes_frame_latch.py verifies the vblank latch ordering and that host refresh does not resample live NES PPU state.
- The container does not include fbc/Wine/pwsh, so native compile/runtime execution remains to be verified in the normal PHLEGM build environment.
